#pragma once
#include "CoreMinimal.h"
#include "GameplayTaskOwnerInterface.h"
#include "SmStepObjectTypes.h"
#include "SmStepObject.generated.h"


DECLARE_DELEGATE(FOnStepEndFinish);

UCLASS(Blueprinttype, Blueprintable)
class SMQUEST_API USmStepObject : public UObject, public IGameplayTaskOwnerInterface
{
	GENERATED_BODY()

public:
	USmStepObject();

	// --------------------------------------
	//	UObject overrides
	// --------------------------------------	
	virtual UWorld* GetWorld() const override;
	virtual int32 GetFunctionCallspace(UFunction* Function, FFrame* Stack) override;
	virtual bool CallRemoteFunction(UFunction* Function, void* Parameters, FOutParmRec* OutParms, FFrame* Stack) override;
	virtual bool IsSupportedForNetworking() const override;

	// --------------------------------------
	//	IGameplayTaskOwnerInterface
	// --------------------------------------	
	virtual UGameplayTasksComponent* GetGameplayTasksComponent(const UGameplayTask& Task) const override;
	virtual AActor* GetGameplayTaskOwner(const UGameplayTask* Task) const override;
	virtual AActor* GetGameplayTaskAvatar(const UGameplayTask* Task) const override;
	virtual void OnGameplayTaskInitialized(UGameplayTask& Task) override;
	virtual void OnGameplayTaskActivated(UGameplayTask& Task) override;
	virtual void OnGameplayTaskDeactivated(UGameplayTask& Task) override;
	
	// --------------------------------------
	//	Accessors
	// --------------------------------------
	
	/** True if this has been instanced, always true for blueprints */
	bool IsInstantiated() const;

	/** How an ability replicates state/events to everyone on the network */
	ESmStepObjectReplicationPolicy::Type GetReplicationPolicy() const
	{
		return ReplicationPolicy;
	}

	/** Gets the current actor info bound to this ability - can only be called on instanced abilities. */
	const FSmStepObjectActorInfo* GetCurrentActorInfo() const
	{
		check(IsInstantiated());
		return CurrentActorInfo;
	}
	
	// --------------------------------------
	//	Delegates
	// --------------------------------------

	// Step彻底结束时调用，组件的方法绑到它上面，单播，不能绑其他的东西
	FOnStepEndFinish OnStepEndFinish;
	
protected:
	// --------------------------------------
	//	CanStepStart
	// --------------------------------------
	
	virtual bool CanStepStart();

	// --------------------------------------
	//	StepStart
	// --------------------------------------
	
	UFUNCTION(BlueprintImplementableEvent, Category = SmQuest, DisplayName = "StepStart", meta=(ScriptName = "StepStart"))
	void K2_StepStart();
	bool bHasBlueprintStepStart;
	
	virtual void StepStart();

	virtual void PreStepStart();
	
	// 用来给组件进行调用，作为内部开始一个step的逻辑起点，里面调用PreStepStart和StepStart
	void CallStepStart();

	UFUNCTION(BlueprintCallable, Category = SmQuest, DisplayName="StepStartFinish", meta=(ScriptName = "StepStartFinish"))
	virtual void K2_StepStartFinish();

	virtual void StepStartFinish();

	// --------------------------------------
	//	StepSuccessCondition
	// --------------------------------------
	
	UFUNCTION(BlueprintNativeEvent)
	bool StepSuccessCondition();

	bool StepSuccessCondition_Implementation(){ return false; };

	// 在组件中进行Tick调用
	virtual void CheckStepSuccessCondition();

	// --------------------------------------
	//	StepEnd
	// --------------------------------------
	
	UFUNCTION(BlueprintImplementableEvent, Category = SmQuest, DisplayName = "StepEnd", meta=(ScriptName = "StepEnd"))
	void K2_StepEnd();
	bool bHasBlueprintStepEnd;
	
	virtual void StepEnd();

	UFUNCTION(BlueprintCallable, Category = SmQuest, DisplayName="StepEndFinish", meta=(ScriptName = "StepEndFinish"))
	virtual void K2_StepEndFinish();

	virtual void StepEndFinish();
	
	// -------------------------------------
	//	Protected properties
	// -------------------------------------

	/** How an StepObject replicates state/events to everyone on the network. Replication is not required for NetExecutionPolicy. */
	UPROPERTY(EditDefaultsOnly, Category = SmQuest)
	TEnumAsByte<ESmStepObjectReplicationPolicy::Type> ReplicationPolicy;

	// 记录当前Step的状态，是在开始阶段，还是中间等待成功/失败的阶段，还是在结束阶段，还是什么阶段都不是
	UPROPERTY(EditDefaultsOnly, Category = SmQuest)
	TEnumAsByte<ESmStepObjectState::Type> StepObjectState;

	mutable const FSmStepObjectActorInfo* CurrentActorInfo;

	// ----------------------------------------------------------------------------------------------------------------
	//	Ability Tasks
	// ----------------------------------------------------------------------------------------------------------------

	/** List of currently active tasks, do not modify directly */
	UPROPERTY()
	TArray<UGameplayTask*>	ActiveTasks;
};

